package com.biz.primus.ms.commodity.service.frontend;

import com.biz.primus.base.enums.ChannelType;
import com.biz.primus.base.exception.BizParameterException;
import com.biz.primus.base.exception.utils.AssertUtils;
import com.biz.primus.commodity.exception.CommodityExceptionType;
import com.biz.primus.commodity.vo.backend.SearchPageVo;
import com.biz.primus.commodity.vo.evaluation.PageResult;
import com.biz.primus.commodity.vo.evaluation.Pagination;
import com.biz.primus.commodity.vo.evaluation.PaginationResult;
import com.biz.primus.commodity.vo.evaluation.frontend.*;
import com.biz.primus.commodity.vo.unused.MemberIdRequestVo;
import com.biz.primus.commodity.vo.unused.UserResponseVo;
import com.biz.primus.common.utils.JsonUtil;
import com.biz.primus.model.vendor.vo.VendorStatisticVo;
import com.biz.primus.ms.base.service.AbstractBaseService;
import com.biz.primus.ms.commodity.dao.po.Evaluation;
import com.biz.primus.ms.commodity.dao.po.Product;
import com.biz.primus.ms.commodity.dao.redis.EvaluationRedisDao;
import com.biz.primus.ms.commodity.dao.redis.ProductRedisDao;
import com.biz.primus.ms.commodity.dao.repository.evaluation.EvaluationRepository;
import com.biz.primus.ms.commodity.dao.repository.product.ProductRepository;
import com.biz.primus.ms.commodity.dao.ro.EvaluationRo;
import com.biz.primus.ms.commodity.dao.ro.ProductRo;
import com.biz.primus.ms.commodity.feign.UserFeignClient;
import com.biz.primus.ms.commodity.feign.VendorFeignClient;
import com.biz.primus.ms.commodity.trans.EvaluationRo2EvaluationVo;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

import static com.google.common.collect.Lists.newArrayList;

/**
 * @author yangzichun
 * @date 2017/2/15
 */
@Service
@Slf4j
public class EvaluationService extends AbstractBaseService {
    @Autowired
    private EvaluationRepository evaluationRepository;
    @Autowired
    private VendorFeignClient vendorRepository;
    @Autowired
    private ProductRepository productRepository;
    @Autowired
    private EvaluationRedisDao evaluationRedisDao;
    @Autowired
    private ProductRedisDao productRedisDao;
    @Autowired
    private UserFeignClient userService;
    @Autowired
    private VendorFeignClient vendorFeignClient;

    /**
     * 从redis中查询评价 vo 分页结果
     *
     * @param searchPageVo 评价分页请求vo
     * @return 评价 vo 分页结果
     * 参数不合法异常
     */
    public PageResult<EvaluationVo> findEvaluations(SearchPageVo searchPageVo) {
        // searchPageVo对象或pageIndex、pageSize为空
        if (searchPageVo == null || searchPageVo.getPageIndex() < 0 || searchPageVo.getPageSize() <= 0) {
            throw new BizParameterException("请求参数不合法");
        }
        // 根据页数从redis中查询评价ro，第一页为1
        List<EvaluationRo> evaluationRos = evaluationRedisDao.findByScoreDesc(searchPageVo.getPageIndex(),
                searchPageVo.getPageSize());
        // 如果未查询到评价集合,返回new PageResult
        return buildPageResult(searchPageVo, evaluationRos);
    }

    /**
     * 生成返回vo
     *
     * @param searchPageVo
     * @param evaluationRos
     * @return
     */
    private PageResult<EvaluationVo> buildPageResult(SearchPageVo searchPageVo, List<EvaluationRo> evaluationRos) {
        PageResult pageResult;
        if (CollectionUtils.isNotEmpty(evaluationRos)) {
            List<EvaluationVo> evaluationVos = Lists.transform(evaluationRos, new EvaluationRo2EvaluationVo());
            pageResult = new PageResult<>(searchPageVo.getPageIndex() + 1, evaluationVos.size(), evaluationRos.size(),
                    evaluationVos);
        } else {
            pageResult = new PageResult<>(searchPageVo.getPageIndex() + 1, searchPageVo.getPageSize(), 0,
                    newArrayList());
        }
        return pageResult;
    }

    /**
     * 根据店铺 id 从redis中查询评价 vo 分页结果
     * <p>
     * 店铺查询评价分页请求vo
     *
     * @return 评价 vo 分页结果
     * 参数不合法异常
     */
    public PaginationResult<EvaluationVo> findByVendorIdPage(EvaluationRequestDTO requestDTO) {
        if (requestDTO == null || requestDTO.getVendorId() == null) {
            throw new BizParameterException("请求参数不合法");
        }

        // 返回结果对象
        PaginationResult<EvaluationVo> paginationResult = new PaginationResult<EvaluationVo>();

        // 评论内容结果集
        List<EvaluationRo> evaluationRos = evaluationRedisDao.findByVendorId(requestDTO);

        // 数据结果集
        List<EvaluationVo> result = Lists.transform(evaluationRos, new EvaluationRo2EvaluationVo());
        if (result != null) {
            // 获取商品评论总数
            Long total = evaluationRedisDao.countByVendorIdTotal(String.valueOf(requestDTO.getVendorId()));
            // 构建分页处理对象
            Pagination pagination = new Pagination(requestDTO.getPage(), requestDTO.getLimit(), total.intValue());

            paginationResult.setPagination(pagination);
            paginationResult.setResult(buildEvaluationsUserInfo(result));
        }
        return paginationResult;
    }

    /**
     * 保存或更新一条评价
     *
     * @param evaluationAddVo 评价vo
     */
    @Transactional
    public void saveOrUpdateEvaluation(EvaluationAddVo evaluationAddVo) {
        if (log.isDebugEnabled()) {
            log.debug("保存评价信息,参数[{}]", JsonUtil.obj2Json(evaluationAddVo));
        }
        // 判断参数是否为空
        if (evaluationAddVo == null || StringUtils.isBlank(evaluationAddVo.getProductCode())
                || StringUtils.isBlank(evaluationAddVo.getOrderCode())) {
            log.error("传递参数不合法");
            throw new BizParameterException("无效评价");
        }
        Evaluation evaluation = null;
        // 如果这是一条新建的评论,分配id
        if (evaluationAddVo.getId() == null) {
            evaluation = new Evaluation();
            evaluation.setId(idService.getNextId());
            evaluation.setImages(evaluationAddVo.getImages());
        } else {
            // 如果已经存在，从vo中获取id
            evaluation.setId(evaluationAddVo.getId());
        }

        Product product = productRepository.findByProductCode(evaluationAddVo.getProductCode());
        // 检查商品信息，如果为空抛出异常
        AssertUtils.notNull(product, CommodityExceptionType.PRODUCT_NOT_FOUND);
        evaluation.setProduct(product);
        evaluation.setVendorId(evaluationAddVo.getVendorId());
        // 从评价 vo 拷贝除了id、店铺、商品信息以外的信息
        evaluation.fromEvaluationAddVo(evaluationAddVo);
        try {
            Evaluation re = evaluationRepository.save(evaluation);
        } catch (Exception e) {
            log.error("保存评价出错", e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 保存或者更新较多评论
     *
     * @param evaluationAddVos 添加评论vo
     *                         Soa异常
     */
    public void saveOrUpdateEvaluations(List<EvaluationAddVo> evaluationAddVos) {
        AssertUtils.notEmpty(evaluationAddVos, CommodityExceptionType.REQUEST_PARAM_EXCEPTION);
        List<Evaluation> evaluations = Lists.newArrayList();
        for (EvaluationAddVo evaluationAddVo : evaluationAddVos) {
            log.info("评价 vo {}", JsonUtil.obj2Json(evaluationAddVo));
            Evaluation evaluation = new Evaluation();
            if (evaluationAddVo.getId() == null) {
                evaluation.setId(idService.getNextId());
            } else {
                // 如果已经存在，从vo中获取id
                evaluation.setId(evaluationAddVo.getId());
            }
            Product product = productRepository.findByProductCode(evaluationAddVo.getProductCode());
            // 检查商品信息，如果为空抛出异常
            AssertUtils.notNull(product,CommodityExceptionType.PRODUCT_NOT_FOUND);
            // 如果店铺信息为空，判断是否为B类商品，如果是，抛出异常
            evaluation.setVendorId(evaluationAddVo.getVendorId());
            // 设置评价的id、店铺、商品信息
            evaluation.setProduct(product);
            // 从评价 vo 拷贝除了id、店铺、商品信息以外的信息
            evaluation.fromEvaluationAddVo(evaluationAddVo);
            evaluations.add(evaluation);
        }
        try {
            log.info("开始保存评价，共{}个", evaluations.size());
            evaluationRepository.save(evaluations);
        } catch (Exception e) {
            log.error("保存评价出错", e.getMessage(), e);
        }
    }

    /**
     * 获取店铺总评价
     *
     * @return
     */
    public EvaluationCountVo findAllEvaluationByVendorId(VendorIdPageRequestVo vo) {
        if (vo == null || vo.getProductId() == null) {
            throw new BizParameterException("请求参数不合法");
        }
        VendorStatisticVo vendorRo = vendorFeignClient.getVendorStastic(vo.getVendorId());
        EvaluationCountVo evaluationCountVo = new EvaluationCountVo();
        if (vendorRo != null) {
            evaluationCountVo.setAttitudeNum(vendorRo.getAttitudeNum());
            evaluationCountVo.setAttitudeScore(vendorRo.getAttitudeScore());
            evaluationCountVo.setDescriptionNum(vendorRo.getDescriptionNum());
            evaluationCountVo.setDescriptionScore(vendorRo.getDescriptionScore());
            evaluationCountVo.setLogisticsNum(vendorRo.getLogisticsNum());
            evaluationCountVo.setLogisticsScore(vendorRo.getLogisticsScore());
        }
        return evaluationCountVo;

    }

    /**
     * 根据商品Id获取总评价
     */
    public EvaluationCountVo findEvaluationCountByProductCode(EvaluationRequestDTO requestDTO) {
        if (requestDTO.getProductCode() == null || requestDTO == null || requestDTO.getVendorId() == null) {
            throw new BizParameterException("请求参数不合法");
        }
        ProductRo productRo = productRedisDao.findOne(requestDTO.getProductCode());
        VendorStatisticVo vendorRo = vendorFeignClient.getVendorStastic(requestDTO.getVendorId());
        EvaluationCountVo evaluationCountVo = new EvaluationCountVo();
        if (vendorRo != null) {
            evaluationCountVo.setAttitudeScore(vendorRo.getAttitudeScore());
            evaluationCountVo.setLogisticsScore(vendorRo.getLogisticsScore());
            evaluationCountVo.setDescriptionScore(vendorRo.getLogisticsScore());
            evaluationCountVo.setProductscore(productRo.getScore());
        }
        return evaluationCountVo;
    }

    /**
     * 备注：该方法由于Vo的中参数没有设置完成，并且该方法用于导入订单时使用，其他地方请慎用
     *
     * @return
     */
    public List<EvaluationVo> findAllEvaluations() {
        List<Evaluation> evaluations = evaluationRepository.findAll();
        log.debug("所有的评价的数量为：{}", evaluations.size());
        List<EvaluationVo> evaluationVos = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(evaluations)) {
            for (Evaluation evaluation : evaluations) {
                EvaluationVo evaluationVo = new EvaluationVo();
                evaluationVo.setId(evaluation.getId());
                evaluationVo.setOrderCode(evaluation.getOrderCode());
                evaluationVo.setMemberId(evaluation.getMemberId());
                evaluationVos.add(evaluationVo);
            }
            return evaluationVos;
        }
        return Lists.newArrayList();
    }

    public PaginationResult<EvaluationVo> getPaginationResult(EvaluationRequestDTO requestDTO) {
        if (requestDTO == null || (requestDTO.getProductId() == null && requestDTO.getProductCode() == null)) {
            throw new BizParameterException("请求参数不合法");
        }
        if (requestDTO.getProductCode() == null) {
            requestDTO.setProductCode(productRedisDao.getProductCodeById(requestDTO.getProductId()));
        }
        // 返回结果对象
        PaginationResult<EvaluationVo> paginationResult = new PaginationResult<EvaluationVo>();

        // 评论内容结果集
        List<EvaluationRo> evaluationRos = evaluationRedisDao.findByEvaluationProductCode(requestDTO);

        // 数据结果集
        List<EvaluationVo> result = Lists.transform(evaluationRos, new EvaluationRo2EvaluationVo());
        if (result != null) {
            // 获取商品评论总数
            Long total = evaluationRedisDao.countByProductCodeTotal(requestDTO.getProductCode());
            // 构建分页处理对象
            Pagination pagination = new Pagination(requestDTO.getPage(), requestDTO.getLimit(), total.intValue());

            paginationResult.setPagination(pagination);
            paginationResult.setResult(buildEvaluationsUserInfo(result));
        }
        return paginationResult;
    }

    public EvaluationPageWithAvgScoreVo getEvaluationPageWithScore(EvaluationRequestDTO requestVo) {
        PaginationResult<EvaluationVo> paginationResult = this.getPaginationResult(requestVo);
        EvaluationCountVo evaluationCountByProductCode = this.findEvaluationCountByProductCode(requestVo);
        return new EvaluationPageWithAvgScoreVo(paginationResult, evaluationCountByProductCode);
    }

    private List<EvaluationVo> buildEvaluationsUserInfo(List<EvaluationVo> evaluationVos) {
        if (CollectionUtils.isEmpty(evaluationVos)) {
            return null;
        }
        List<EvaluationVo> result = new ArrayList<>();
        for (EvaluationVo evaluationVo : evaluationVos) {
            buildEvaluationUserInfo(evaluationVo);
            result.add(evaluationVo);
        }
        return result;
    }

    /**
     * 构建商品评论 用户信息
     *
     * @param evaluationVo
     */
    private void buildEvaluationUserInfo(EvaluationVo evaluationVo) {
        if (evaluationVo == null) {
            return;
        }
        MemberIdRequestVo vo = new MemberIdRequestVo();
        vo.setMemberId(evaluationVo.getMemberId());
        vo.setChannelCode(ChannelType.BBC.getCode());
        UserResponseVo userResponseVo = null;
        userResponseVo = userService.findByMemberIdCondition(vo);
        if (userResponseVo == null) {
            return;
        }
        evaluationVo.setNickName(StringUtils.isBlank(userResponseVo.getNickname()) ? userResponseVo.getAccountName()
                : userResponseVo.getNickname());
        evaluationVo.setAvatar(userResponseVo.getAvatar());

    }

}
